"""
Git 操作工具模块

提供 Git 状态、差异、提交、日志等功能。
"""

import re
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional

from .base import GitTool, ToolResult, ToolError


class GitStatusTool(GitTool):
    """Git 状态工具"""
    
    def __init__(self):
        super().__init__(
            name="git_status",
            description="获取 Git 仓库状态信息",
            version="1.0.0"
        )
    
    def get_parameters(self) -> Dict[str, Dict[str, Any]]:
        return {
            'path': {
                'type': str,
                'required': False,
                'default': '.',
                'description': 'Git 仓库路径（默认当前目录）'
            },
            'porcelain': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '使用简洁格式输出'
            },
            'show_untracked': {
                'type': bool,
                'required': False,
                'default': True,
                'description': '显示未跟踪文件'
            }
        }
    
    def execute(self, **kwargs) -> ToolResult:
        """执行 Git 状态检查"""
        start_time = datetime.now()
        
        try:
            if not self.validate_parameters(**kwargs):
                return self._create_result(False, error="参数验证失败")
            
            path = Path(kwargs.get('path', '.'))
            porcelain = kwargs.get('porcelain', False)
            show_untracked = kwargs.get('show_untracked', True)
            
            # 获取仓库根目录
            repo_root = self._get_repo_root(path)
            
            # 构建 git status 命令
            args = ['status']
            if porcelain:
                args.append('--porcelain')
            if show_untracked:
                args.append('--untracked-files=all')
            else:
                args.append('--untracked-files=no')
            
            # 执行命令
            output = self._run_git_command(args, cwd=repo_root)
            
            # 解析状态信息
            if porcelain:
                status_data = self._parse_porcelain_status(output)
            else:
                status_data = self._parse_status_output(output)
            
            execution_time = (datetime.now() - start_time).total_seconds()
            
            return self._create_result(
                success=True,
                data=status_data,
                message="Git 状态获取成功",
                execution_time=execution_time,
                metadata={
                    'repo_root': str(repo_root),
                    'porcelain': porcelain
                }
            )
            
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds()
            return self._create_result(
                success=False,
                error=str(e),
                execution_time=execution_time
            )
    
    def _parse_porcelain_status(self, output: str) -> Dict[str, Any]:
        """解析简洁格式的状态输出"""
        files = {
            'staged': [],
            'modified': [],
            'untracked': [],
            'deleted': [],
            'renamed': [],
            'conflicts': []
        }
        
        for line in output.strip().split('\n'):
            if not line:
                continue
            
            status = line[:2]
            filename = line[3:]
            
            if status[0] == 'A':  # Added
                files['staged'].append({'file': filename, 'status': 'added'})
            elif status[0] == 'M':  # Modified
                files['staged'].append({'file': filename, 'status': 'modified'})
            elif status[0] == 'D':  # Deleted
                files['staged'].append({'file': filename, 'status': 'deleted'})
            elif status[0] == 'R':  # Renamed
                files['staged'].append({'file': filename, 'status': 'renamed'})
            
            if status[1] == 'M':  # Modified
                files['modified'].append({'file': filename, 'status': 'modified'})
            elif status[1] == 'D':  # Deleted
                files['deleted'].append({'file': filename, 'status': 'deleted'})
            elif status[1] == 'U':  # Unmerged
                files['conflicts'].append({'file': filename, 'status': 'conflict'})
            
            if status == '??':  # Untracked
                files['untracked'].append({'file': filename, 'status': 'untracked'})
        
        return {
            'format': 'porcelain',
            'files': files,
            'summary': {
                'staged_count': len(files['staged']),
                'modified_count': len(files['modified']),
                'untracked_count': len(files['untracked']),
                'deleted_count': len(files['deleted']),
                'conflicts_count': len(files['conflicts'])
            }
        }
    
    def _parse_status_output(self, output: str) -> Dict[str, Any]:
        """解析标准格式的状态输出"""
        lines = output.strip().split('\n')
        
        # 提取分支信息
        branch_info = {}
        for line in lines:
            if line.startswith('On branch'):
                branch_info['current_branch'] = line.split('On branch ')[1]
            elif 'Your branch is ahead of' in line:
                branch_info['ahead'] = True
            elif 'Your branch is behind' in line:
                branch_info['behind'] = True
            elif 'Your branch is up to date' in line:
                branch_info['up_to_date'] = True
        
        # 解析文件状态
        files = {
            'staged': [],
            'modified': [],
            'untracked': [],
            'deleted': []
        }
        
        current_section = None
        for line in lines:
            if 'Changes to be committed:' in line:
                current_section = 'staged'
            elif 'Changes not staged for commit:' in line:
                current_section = 'modified'
            elif 'Untracked files:' in line:
                current_section = 'untracked'
            elif line.startswith('\t') and current_section:
                filename = line.strip()
                if filename:
                    files[current_section].append(filename)
        
        return {
            'format': 'standard',
            'branch': branch_info,
            'files': files,
            'summary': {
                'staged_count': len(files['staged']),
                'modified_count': len(files['modified']),
                'untracked_count': len(files['untracked']),
                'deleted_count': len(files['deleted'])
            }
        }


class GitDiffTool(GitTool):
    """Git 差异工具"""
    
    def __init__(self):
        super().__init__(
            name="git_diff",
            description="显示 Git 差异信息",
            version="1.0.0"
        )
    
    def get_parameters(self) -> Dict[str, Dict[str, Any]]:
        return {
            'path': {
                'type': str,
                'required': False,
                'default': '.',
                'description': 'Git 仓库路径'
            },
            'staged': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '显示暂存区的差异'
            },
            'file': {
                'type': str,
                'required': False,
                'description': '指定文件路径'
            },
            'commit_range': {
                'type': str,
                'required': False,
                'description': '提交范围（如 HEAD~1..HEAD）'
            },
            'stat': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '显示统计信息'
            }
        }
    
    def execute(self, **kwargs) -> ToolResult:
        """执行 Git 差异检查"""
        start_time = datetime.now()
        
        try:
            if not self.validate_parameters(**kwargs):
                return self._create_result(False, error="参数验证失败")
            
            path = Path(kwargs.get('path', '.'))
            staged = kwargs.get('staged', False)
            file_path = kwargs.get('file')
            commit_range = kwargs.get('commit_range')
            stat = kwargs.get('stat', False)
            
            repo_root = self._get_repo_root(path)
            
            # 构建 git diff 命令
            args = ['diff']
            if staged:
                args.append('--cached')
            if stat:
                args.append('--stat')
            if commit_range:
                args.append(commit_range)
            if file_path:
                args.append(file_path)
            
            output = self._run_git_command(args, cwd=repo_root)
            
            execution_time = (datetime.now() - start_time).total_seconds()
            
            return self._create_result(
                success=True,
                data={
                    'diff': output,
                    'staged': staged,
                    'file': file_path,
                    'commit_range': commit_range,
                    'stat': stat
                },
                message="Git 差异获取成功",
                execution_time=execution_time,
                metadata={
                    'repo_root': str(repo_root)
                }
            )
            
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds()
            return self._create_result(
                success=False,
                error=str(e),
                execution_time=execution_time
            )


class GitCommitTool(GitTool):
    """Git 提交工具"""
    
    def __init__(self):
        super().__init__(
            name="git_commit",
            description="执行 Git 提交操作",
            version="1.0.0"
        )
    
    def get_parameters(self) -> Dict[str, Dict[str, Any]]:
        return {
            'path': {
                'type': str,
                'required': False,
                'default': '.',
                'description': 'Git 仓库路径'
            },
            'message': {
                'type': str,
                'required': True,
                'description': '提交消息'
            },
            'files': {
                'type': list,
                'required': False,
                'description': '要提交的文件列表（空则提交所有暂存文件）'
            },
            'amend': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '修改最后一次提交'
            },
            'dry_run': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '仅显示将要提交的内容，不实际提交'
            }
        }
    
    def execute(self, **kwargs) -> ToolResult:
        """执行 Git 提交"""
        start_time = datetime.now()
        
        try:
            if not self.validate_parameters(**kwargs):
                return self._create_result(False, error="参数验证失败")
            
            path = Path(kwargs.get('path', '.'))
            message = kwargs['message']
            files = kwargs.get('files', [])
            amend = kwargs.get('amend', False)
            dry_run = kwargs.get('dry_run', False)
            
            repo_root = self._get_repo_root(path)
            
            if dry_run:
                # 显示将要提交的内容
                args = ['diff', '--cached']
                if files:
                    args.extend(files)
                output = self._run_git_command(args, cwd=repo_root)
                
                execution_time = (datetime.now() - start_time).total_seconds()
                return self._create_result(
                    success=True,
                    data={'diff': output, 'dry_run': True},
                    message="预览提交内容",
                    execution_time=execution_time
                )
            
            # 添加文件到暂存区
            if files:
                add_args = ['add'] + files
                self._run_git_command(add_args, cwd=repo_root)
            
            # 执行提交
            commit_args = ['commit', '-m', message]
            if amend:
                commit_args.append('--amend')
            
            output = self._run_git_command(commit_args, cwd=repo_root)
            
            execution_time = (datetime.now() - start_time).total_seconds()
            
            return self._create_result(
                success=True,
                data={
                    'commit_output': output,
                    'message': message,
                    'files': files,
                    'amend': amend
                },
                message="Git 提交成功",
                execution_time=execution_time,
                metadata={
                    'repo_root': str(repo_root)
                }
            )
            
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds()
            return self._create_result(
                success=False,
                error=str(e),
                execution_time=execution_time
            )


class GitLogTool(GitTool):
    """Git 日志工具"""
    
    def __init__(self):
        super().__init__(
            name="git_log",
            description="获取 Git 提交日志",
            version="1.0.0"
        )
    
    def get_parameters(self) -> Dict[str, Dict[str, Any]]:
        return {
            'path': {
                'type': str,
                'required': False,
                'default': '.',
                'description': 'Git 仓库路径'
            },
            'count': {
                'type': int,
                'required': False,
                'default': 10,
                'min': 1,
                'max': 1000,
                'description': '显示提交数量'
            },
            'author': {
                'type': str,
                'required': False,
                'description': '按作者过滤'
            },
            'since': {
                'type': str,
                'required': False,
                'description': '开始时间（如 "2023-01-01"）'
            },
            'until': {
                'type': str,
                'required': False,
                'description': '结束时间（如 "2023-12-31"）'
            },
            'file': {
                'type': str,
                'required': False,
                'description': '指定文件路径'
            },
            'oneline': {
                'type': bool,
                'required': False,
                'default': False,
                'description': '单行格式显示'
            }
        }
    
    def execute(self, **kwargs) -> ToolResult:
        """执行 Git 日志查询"""
        start_time = datetime.now()
        
        try:
            if not self.validate_parameters(**kwargs):
                return self._create_result(False, error="参数验证失败")
            
            path = Path(kwargs.get('path', '.'))
            count = kwargs.get('count', 10)
            author = kwargs.get('author')
            since = kwargs.get('since')
            until = kwargs.get('until')
            file_path = kwargs.get('file')
            oneline = kwargs.get('oneline', False)
            
            repo_root = self._get_repo_root(path)
            
            # 构建 git log 命令
            args = ['log']
            if oneline:
                args.append('--oneline')
            else:
                args.extend(['--pretty=format:%H|%an|%ae|%ad|%s', '--date=iso'])
            
            args.extend(['-n', str(count)])
            
            if author:
                args.extend(['--author', author])
            if since:
                args.extend(['--since', since])
            if until:
                args.extend(['--until', until])
            if file_path:
                args.append('--')
                args.append(file_path)
            
            output = self._run_git_command(args, cwd=repo_root)
            
            # 解析日志
            if oneline:
                commits = self._parse_oneline_log(output)
            else:
                commits = self._parse_detailed_log(output)
            
            execution_time = (datetime.now() - start_time).total_seconds()
            
            return self._create_result(
                success=True,
                data={
                    'commits': commits,
                    'count': len(commits),
                    'oneline': oneline
                },
                message=f"获取到 {len(commits)} 条提交记录",
                execution_time=execution_time,
                metadata={
                    'repo_root': str(repo_root),
                    'filters': {
                        'author': author,
                        'since': since,
                        'until': until,
                        'file': file_path
                    }
                }
            )
            
        except Exception as e:
            execution_time = (datetime.now() - start_time).total_seconds()
            return self._create_result(
                success=False,
                error=str(e),
                execution_time=execution_time
            )
    
    def _parse_oneline_log(self, output: str) -> List[Dict[str, Any]]:
        """解析单行格式的日志"""
        commits = []
        for line in output.strip().split('\n'):
            if not line:
                continue
            
            parts = line.split(' ', 1)
            if len(parts) == 2:
                commits.append({
                    'hash': parts[0],
                    'message': parts[1]
                })
        
        return commits
    
    def _parse_detailed_log(self, output: str) -> List[Dict[str, Any]]:
        """解析详细格式的日志"""
        commits = []
        for line in output.strip().split('\n'):
            if not line:
                continue
            
            parts = line.split('|')
            if len(parts) >= 5:
                commits.append({
                    'hash': parts[0],
                    'author_name': parts[1],
                    'author_email': parts[2],
                    'date': parts[3],
                    'message': parts[4]
                })
        
        return commits
